﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using System.Text.RegularExpressions;
//using Windows.Data.Xml.Dom;
using System.Diagnostics;
//using System.Net.Http;

namespace Utilities.Xml
{
    public class XHelperStringList
    {
        private List<string> list = new List<string>();
        public XHelperStringList(List<string> inList)
        { list.AddRange(inList); }
        public string GetFirstString() { return ""; }

    }

    public static class XHelper
    {

        public static int DefaultIntValue = Int32.MinValue;
        public static bool DefaultBoolValue = false;
        public static double DefaultDoubleValue = 0.0;
        public static DateTime DefaultDateValue = DateTime.Parse("1/1/1900 AM").Date;
        public static DateTime DefaultDateTimeValue = DateTime.Parse("1/1/1900 AM");
        public static string DefaultTimeString = "00:00 AM";
        public static string DefaultString = "xxxx";


        public static string PadWithZeros(string TheValue, int NumDecimals)
        {
            string[] numbers = TheValue.Split('.');

            int NumZerosNeeded = 0;

            if (numbers.Length == 1)
            {
                NumZerosNeeded = NumDecimals;
                TheValue += ".";
            }
            else if (numbers[1] != null)
            {
                NumZerosNeeded = NumDecimals - numbers[1].Length;
            }
            for (int ii = 0; ii < NumZerosNeeded; ii++)
            {
                TheValue += "0";
            }
            return TheValue;
        }


        public static string GetElementAttributeValue(XElement elem, string AttName)
        {
            return GetAttributeValue(elem.Attributes().SingleOrDefault<XAttribute>(x => (x.Name == AttName)));
        }
        public static int GetElementAttributeValueAsInt(XElement elem, string AttName)
        {
            return GetAttributeValueAsInt(elem.Attributes().SingleOrDefault<XAttribute>(x => (x.Name == AttName)));
        }
        public static double GetElementAttributeValueAsDouble(XElement elem, string AttName)
        {
            return GetAttributeValueAsDouble(elem.Attributes().SingleOrDefault<XAttribute>(x => (x.Name == AttName)));
        }
        public static bool GetElementAttributeValueAsBool(XElement elem, string AttName)
        {
            return GetElementAttributeValueAsInt(elem, AttName) == 1 ? true : false;
        }
        public static bool? GetElementAttributeValueAsBoolean(XElement elem, string AttName)
        {
            string boolvaluestr = GetElementAttributeValue(elem, AttName);

            bool boolvalue;
            if (bool.TryParse(boolvaluestr, out boolvalue))
            {
                return boolvalue;
            }
            else
            {
                return null;
            }
        }
        public static DateTime GetElementAttributeValueAsDateTime(XElement elem, string AttName)
        {
            return GetAttributeValueAsDateTime(elem.Attributes().SingleOrDefault<XAttribute>(x => (x.Name == AttName)));
        }

        //XML => string Value
        public static string GetAttributeValue(XAttribute att)
        {
            try
            {
                return (att == null ? "" : att.Value);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            return "";
        }
        public static string GetAttributeDecimalValue(XAttribute att)
        {
            try
            {
                return (att == null ? "0.0" : att.Value);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            return "";
        }
        public static string GetAttributeIntValue(XAttribute att)
        {
            try
            {
                string ss = att == null ? DefaultIntValue.ToString() : att.Value;
                return ss;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            return "";
        }


        //XML => DataType Value
        public static int GetAttributeValueAsInt(XAttribute att)
        {
            try
            {
                if (att == null)
                {
                    return DefaultIntValue;
                }
                int value;
                if (Int32.TryParse(att.Value, out value))
                {
                    return value;
                }
                else
                {
                    return DefaultIntValue;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            return DefaultIntValue;
        }

        public static double GetAttributeValueAsDouble(XAttribute att)
        {
            try
            {
                if (att == null)
                {
                    return DefaultDoubleValue;
                }
                double value;
                if (Double.TryParse(att.Value, out value))
                {
                    return value;
                }
                else
                {
                    return DefaultDoubleValue;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            return DefaultIntValue;
        }

        public static DateTime GetAttributeValueAsDateTime(XAttribute att)
        {
            try
            {
                if (att == null)
                {
                    return DefaultDateTimeValue;
                }
                DateTime value;
                if (DateTime.TryParse(GetAttributeValue(att), out value))
                {
                    return value;
                }
                else
                {
                    return DefaultDateTimeValue;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            return DefaultDateTimeValue;

        }
        /// //////////////////////////////////////////////////////////



        public static IEnumerable<XElement> GetElements(XElement aaaa, string Namespace, string Name)
        {
            return from el in aaaa.Descendants()
                   where (el.Name.Namespace == Namespace && el.Name.LocalName == Name)
                   select el;
        }



        public static IEnumerable<XElement> GetElements(XElement aaaa, string Name)
        {
            return from el in aaaa.Descendants()
                   where (el.Name.LocalName == Name)
                   select el;
        }


        /// ELEMENT VALUE ////////////////////////////////////////
        /// 

        public static XElement GetElement(XElement aaaa, string Namespace, string Name)
        {
            IEnumerable<XElement> loc = from el in aaaa.Descendants()
                                        where (el.Name.Namespace == Namespace && el.Name.LocalName == Name)
                                        select el;
            return loc.Any<XElement>() ? loc.First<XElement>() : null;
        }


        //public static IEnumerable<XElement> GetElements(XElement aaaa, string Name)
        //{
        //    IEnumerable<XElement> loc = aaaa.Elements(Name);
        //    if (loc == null) return null;
        //    //return loc.Count() > 0 ? loc: null;
        //    bool batt = loc.Attributes().Any<XAttribute>();
        //    if (batt)
        //    {
        //        return loc.Any<XElement>() ? loc : null;
        //    }
        //    else
        //    {
        //        return null;
        //    }
        //}


        public static XElement GetDecendantElement(XElement XmlElem, string ElementName)
        {
            try
            {

                while (XmlElem != null && XmlElem.HasElements)
                {
                    if (XHelper.GetElement(XmlElem, ElementName) != null)
                    {
                        XElement XmlConfigEle = XHelper.GetElement(XmlElem, ElementName);
                        return XmlConfigEle;
                    }

                    //IEnumerable<XElement> Data = XmlElem.Elements();
                    //XmlElem = Data.Any<XElement>() ? Data.First<XElement>() : null;
                    XmlElem = XmlElem.FirstNode as XElement;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            return null;
        }



        public static XElement GetElement(XElement aaaa, string Name)
        {
            //IEnumerable<XElement> loc = aaaa.Elements(Name);
            //if (loc == null) return null;
            //return loc.Any<XElement>() ? loc.First<XElement>() : null;


            IEnumerable<XElement> loc = from el in aaaa.Descendants()
                                        where (el.Name.LocalName == Name)
                                        select el;
            return loc.Any<XElement>() ? loc.First<XElement>() : null;
        }


        public static string GetStringValue(XElement element)
        {
            try
            {
                if (element == null)
                {
                    return "";
                }
                else if (element.Value == null)
                {
                    return "";
                }
                return element.Value;

            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            return "exception";
        }

        public static Int32 GetIntValue(XElement element)
        {
            try
            {
                if (element == null)
                {
                    return DefaultIntValue;
                }
                int value;
                if (Int32.TryParse(element.Value, out value))
                {
                    return value;
                }
                else
                {
                    return DefaultIntValue;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            return DefaultIntValue;
        }

        public static double GetDoubleValue(XElement element)
        {
            try
            {
                if (element == null)
                {
                    return DefaultDoubleValue;
                }
                double value;
                if (Double.TryParse(element.Value, out value))
                {
                    return value;
                }
                else
                {
                    return DefaultIntValue;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            return DefaultIntValue;
        }

        public static DateTime GetDateTimeValue(XElement element)
        {
            try
            {
                if (element == null)
                {
                    return DefaultDateTimeValue;
                }
                DateTime value;
                if (DateTime.TryParse(element.Value, out value))
                {
                    return value;
                }
                else
                {
                    return DefaultDateTimeValue;
                }

            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            return DefaultDateTimeValue;
        }

        public static bool GetBoolValue(XElement element)
        {
            try
            {
                if (element == null)
                {
                    return DefaultBoolValue;
                }
                bool value;
                if (bool.TryParse(element.Value, out value))
                {
                    return value;
                }
                else
                {
                    return DefaultBoolValue;
                }

            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            return DefaultBoolValue;
        }

        public static bool GetStringValueAsBool(XElement element)
        {
            try
            {
                return GetStringValue(element) == "true" ? true : false;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            return false;
        }

        public static string GetXDocumentAsStringValue(XElement element)
        {
            try
            {
                if (element == null)
                {
                    return "";
                }
                else if (element.Value == null)
                {
                    return "";
                }

                string str = element.ToString();
                str = Regex.Replace(str, "[\n\r\t]", " ");
                return str;

            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            return "exception";
        }

        public static XDocument GetXMLDocumentValue(XElement element)
        {
            try
            {
                if (element == null)
                {
                    return null;
                }
                string xml = Regex.Replace(element.ToString(), "[\n\r\t]", " ");
                XDocument xdoc = XDocument.Parse(xml);
                return xdoc;

            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            return null;
        }

        public static XDocument GetXMLDocumentValue(string DocumentName, XElement element)
        {
            try
            {
                if (element == null)
                {
                    return null;
                }
                //XDocument xdoc = new XDocument(DocumentName, element);
                XDocument xdoc = new XDocument(element);
                return xdoc;

            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            return null;
        }


        // DATA VALIDATORS/////////////////////////////////////////
        public static bool IsInValidString(string str)
        {
            if (str == null)
            {
                return true;
            }
            else
            {
                str.Trim();
                str.ToLower();

                if (str == "" || str == "null" || str == "exception")
                {
                    return true;
                }
            }
            return false;
        }

        public static bool StringsMatch(string one, string two)
        {

            if (one.Trim().ToUpper() == two.Trim().ToUpper())
                return true;
            else
                return false;
        }



        // TIME METHODS/////////////////////////////////////////
        public static bool HoursAndMinutes(string timestring, out int hours, out int minutes)
        {
            bool succ = false;
            hours = -1;
            minutes = -1;
            if (!IsInValidString(timestring))
            {
                if (TimeValidationRule(timestring))
                {
                    timestring = timestring.Trim().ToUpper();

                    string hoursstr = timestring.Substring(0, timestring.IndexOf(":"));

                    string minutesstr = timestring.Substring(timestring.IndexOf(":") + 1, 2);

                    string AMPM = timestring.Substring(timestring.Length - 2, 2);

                    if (Int32.TryParse(hoursstr, out hours))
                    {
                        if (Int32.TryParse(minutesstr, out minutes))
                        {
                            if (AMPM.Contains("PM"))
                            {
                                hours = hours + 12;
                            }
                            succ = true;
                        }
                        else
                        {
                            succ = false;
                        }
                    }
                    else
                    {
                        succ = false;
                    }
                }
            }
            return succ;
        }

        
        public static int CalulateElapsedTime(DateTime StartDate, DateTime EndDate)
        {
            int minutes = 0;
            try
            {
                TimeSpan QueuedTimeTS = EndDate - StartDate;
                minutes = QueuedTimeTS.Days * 24 * 60 + QueuedTimeTS.Hours * 60 + QueuedTimeTS.Minutes; ;

                return minutes;
            }
            catch
            {
            }
            return minutes;
        }

    
        public static bool TimeValidationRule(string TheTimeString)
        {
            TheTimeString = TheTimeString.Trim().ToUpper();

            if (TheTimeString == null || TheTimeString == "")
            {
                return false;
            }

            if (TheTimeString.Contains("00:00"))
            {
                return false;
            }

            //Regex checktime = new Regex(@"^((([0]?[1-9]|1[0-2])(:|\.)[0-5][0-9]((:|\.)[0-5][0-9])?( )?(AM|am|aM|Am|PM|pm|pM|Pm))|(([0]?[0-9]|1[0-9]|2[0-3])(:|\.)[0-5][0-9]((:|\.)[0-5][0-9])?))$");
            Regex checktime = new Regex(@"^((([0]?[1-9]|1[0-2])(:|\.)[0-5][0-9]((:|\.)[0-5][0-9])?( )?(AM|am|aM|Am|PM|pm|pM|Pm)))");

            if (checktime.IsMatch(TheTimeString))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public static bool IsValidTime(string TheTimeString)
        {
            TheTimeString = TheTimeString.Trim().ToUpper();

            if (!XHelper.IsInValidString(TheTimeString) && !TheTimeString.Contains("00:00"))
            {
                if (TimeValidationRule(TheTimeString))
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }


        //private static async Task<string> ProcessWithXLinq()
        //{
        //    // you need to acquire a Bing Maps key. See http://www.bingmapsportal.com/
        //    string bingMapKey = "INSERT_YOUR_BING_MAPS_KEY";
        //    // the following uri will returns a response with xml content
        //    Uri uri = new Uri(String.Format("http://dev.virtualearth.net/REST/v1/Locations?q=manchester&o=xml&key={0}", bingMapKey));

        //    HttpClient client = new HttpClient();
        //    HttpResponseMessage response = await client.GetAsync(uri);
        //    response.EnsureSuccessStatusCode();

        //    // ReadAsStreamAsync() returns when the whole message is downloaded
        //    Stream stream = await response.Content.ReadAsStreamAsync();

        //    XDocument xdoc = XDocument.Load(stream);
        //    XNamespace xns = "http://schemas.microsoft.com/search/local/ws/rest/v1";
        //    var addresses = from node in xdoc.Descendants(xns + "Address")                               // query node named "Address"
        //                    where node.Element(xns + "CountryRegion").Value.Contains("United States")    // where CountryRegion contains "United States"
        //                    select node.Element(xns + "FormattedAddress").Value;                         // select the FormattedAddress node's value

        //    StringBuilder stringBuilder = new StringBuilder("Manchester in US: ");
        //    foreach (string name in addresses)
        //        stringBuilder.Append(name + "; ");

        //    return stringBuilder.ToString();
        //}

    }

}
